/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
  <file> uls_conf.h </file>
  <brief>
    Loading the lexical spec file (*.ulc) of ULS.
    This file is part of ULS, Unified Lexical Scheme.
  </brief>
  <author>
    Stanley J. Hong <babel96@gmail.com>, April 2011.
  </author>
*/
#ifndef __ULS_CONF_H__
#define __ULS_CONF_H__

#include "uls_const.h"
#include "uls_type.h"
#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif

#define ULS_KEYW_TYPE_IDSTR      0
#define ULS_KEYW_TYPE_INTRINSIC  1
#define ULS_KEYW_TYPE_1CHAR      2
#define ULS_KEYW_TYPE_RESERVED   3
#define ULS_KEYW_TYPE_LITERAL    4

#define ULS_TOKDEF_FL_RSVD         0x01
#define ULS_TOKDEF_FL_TOKID_LEADER 0x02

struct _uls_tokdef {
	uls_uint32 flags;
	int  tok_id;
	char name[ULS_LEXSTR_MAXSIZ+1];
	uls_char_t keyword[ULS_LEXSTR_MAXSIZ+1];
	int  l_keyword;
	int  kwrd_type;
	uls_tokdef_t  *hlink;
	uls_tokdef_t  *next;
};

struct _uls_kwtable {
	uls_tokdef_t  **bucket_head;
	int               n_buckets, n_shifts;

	uls_uint32        init_hcode[ULF_MAXDIM_HASHSPACE];
	int               n_init_hcode;

	uls_strcmp_t      lxm_strcmp;
};

struct _uls_kwrd_stat {
	const uls_char_t *kwrd;
	int freq;
	uls_tokdef_t  *kwrd_info;
};

struct _uls_version {
	uls_byte_t  major;
	uls_byte_t  minor;
	uls_byte_t  debug;
	uls_byte_t  sequence;
};

struct _ulf_header {
	uls_version_t filever;
	uls_uint32    init_hcode[ULF_MAXDIM_HASHSPACE];
	int           n_init_hcode;
	uls_char_t          hash_algorithm[ULS_LEXSTR_MAXSIZ+1];
	uls_version_t hfunc_ver;
	int           hash_table_size;
};

struct _ulc_header {
	uls_version_t filever;
	int   n_keys_intrinsic, n_keys_idstr;
	int   n_tokids_uniq;
	int   tok_id_min, tok_id_max;
	int   tok_id_seed;
};

int load_lex_conf(FILE *fin, FILE *fin_ulf, uls_lex_t* uls);

int uls_is_valid_specname(const char* confname);
int uls_get_specname(const char *fpath, char* spec_name);
int uls_generate_tokdef_file(uls_lex_t* uls, char *fpath,
	char* ulc_name, char* class_name, int flags);
#define ULS_FL_WANT_REGULAR_TOKS  0x01
#define ULS_FL_WANT_QUOTE_TOKS    0x02
#define ULS_FL_WANT_RESERVED_TOKS 0x04
#define ULS_FL_C_CONSTANTS_GEN    0x10
#define ULS_FL_C_ENUM             0x20

int ulf_create_file(int n_hcodes, uls_uint32 *hcodes, int htab_siz, uls_kwrd_stat_t *lst, int n_lst, FILE* fout);
uls_char_t* get_keyword_str(uls_lex_t* uls, int t);

uls_tokdef_t* is_keyword_intrinsic(uls_lex_t* uls, uls_char_t* str, int len);
uls_tokdef_t* is_keyword_idstr(uls_lex_t* uls, uls_char_t* kwrd, int l_kwrd);
uls_tokdef_t* is_keyword_1char(uls_lex_t* uls, uls_char_t kwrd);

int uls_is_char_idfirst(uls_lex_t* uls, uls_char_t* lptr);
int uls_is_char_id(uls_lex_t* uls, uls_char_t* lptr);

int lexi_order_ascii(uls_char_t* wrd1, int l_wrd1, uls_char_t* wrd2, int l_wrd2);
int lexi_order_ascii_case(uls_char_t* wrd1, int l_wrd1, uls_char_t* wrd2, int l_wrd2);

int canbe_commtype_mark(uls_char_t* wrd, uls_char_t *str, int* p_len, int* p_n_lfs);
int canbe_quotetype_mark(uls_char_t* wrd, uls_char_t *str, int* p_len);

void uls_init_kwtable(uls_kwtable_t* tbl, int n_slots, uls_strcmp_t cmpfunc);
void uls_reset_kwtable(uls_kwtable_t* tbl, int n_slots, int n_hcodes, uls_uint32 *hcodes);
void uls_deinit_kwtable(uls_kwtable_t* tbl);
uls_tokdef_t* uls_find_kw(uls_kwtable_t* tbl, uls_char_t *idstr, int l_idstr, int* p_hash_val);
int uls_add_kw(uls_kwtable_t* tbl, uls_tokdef_t* e);

int sizeof_kwtable(uls_lex_t* uls);
int ulf_hashfunc(const uls_char_t *name, int n_slots, int n_shifts,
	int n_hcodes, uls_uint32 *hcodes);
uls_kwrd_stat_t* uls_export_kwtable(uls_lex_t* uls, int* p_n_list);
void uls_free_kwrd_stat_list(uls_kwrd_stat_t* lst);
uls_kwrd_stat_t* uls_search_kwrd_stat_sorted(uls_kwrd_stat_t *lst, int n_lst, const uls_char_t* str);
void free_lxm_array(uls_lex_t* uls);

void uls_version_make(uls_version_t* a,
	uls_byte_t v1, uls_byte_t v2, uls_byte_t v3, uls_byte_t v4);
void uls_version_encode(const uls_version_t* a, uls_byte_t* codstr);
void uls_version_decode(uls_byte_t* codstr, uls_version_t* a);
void uls_version_copy(uls_version_t* dst, const uls_version_t* src);
int uls_version_make_string(const uls_version_t* a, char* ver_str);
int uls_version_cmp_code(const uls_version_t* a, const uls_version_t* b);
int uls_version_pars_str(char *lptr, uls_version_t* a);
void uls_list_ulc_searchpaths(const char* confname);

#ifdef __cplusplus
}
#endif

#endif
